package com.cgx.service.impl;

import com.cgx.dao.MessageDao;
import com.cgx.dao.SessionDao;
import com.cgx.dao.SessionUserDao;
import com.cgx.entity.User.FriendRelation;
import com.cgx.entity.User.UserInfo;
import com.cgx.entity.message.Message;
import com.cgx.entity.message.Session;
import com.cgx.entity.message.SessionUser;
import com.cgx.service.SessionService;
import com.cgx.service.UserService;
import com.cgx.service.WebsocketService;
import com.cgx.utils.ResultVoUtils;
import com.cgx.vo.*;
import com.cgx.vo.base.BaseIdListVo;
import com.cgx.vo.user.UserInfoVo;
import com.cgx.vo.websocket.MessageVo;
import com.cgx.vo.websocket.MqMessageVo;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chenguanxin
 * @date 2021-05-26 22:17
 */
@Service
public class SessionServiceImpl implements SessionService {

    @Autowired
    private SessionDao sessionDao;

    @Autowired
    private SessionUserDao sessionUserDao;

    @Autowired
    private WebsocketService websocketService;

    @Autowired
    private UserService userService;

    @Autowired
    private MessageDao messageDao;

    @Override
    public List<Session> findAllSessionByUserId(String userId) {
        return sessionDao.findAllBySessionIdAndIsDelete(userId, 0);
    }

    @Override
    public List<Session> saveAllSession(List<Session> sessionList) {
        List<Session> result = new ArrayList<>();
        for (Session session : sessionList) {
            result.add(sessionDao.save(session));
        }
        return result;
    }

    @Override
    public List<SessionUser> saveAllSessionUser(List<SessionUser> sessionList) {
        List<SessionUser> result = new ArrayList<>();
        for (SessionUser session : sessionList) {
            result.add(sessionUserDao.save(session));
        }
        return result;
    }

    @Override
    public Map<String, ResultVo> sendMessageBySessionId(MessageVo messageVo) {
        Map<String, ResultVo> result = new HashMap<>();
        if (messageVo != null && StringUtils.isNotBlank(messageVo.getSessionId())) {
            List<SessionUser> sessionUserList = sessionUserDao.findAllBySessionIdAndIsDelete(messageVo.getSessionId(), 0);
            if (CollectionUtils.isNotEmpty(sessionUserList)) {
                for (SessionUser sessionUser : sessionUserList) {
                    if (!sessionUser.getUserId().equals(messageVo.getFromUserId())) {
                        MqMessageVo mqMessageVo = new MqMessageVo();
                        mqMessageVo.setToUserId(sessionUser.getUserId());
                        mqMessageVo.setType(1);
                        mqMessageVo.setMessage(messageVo);
                        websocketService.sendMessage(mqMessageVo);
                    }
                }
                ResultVo successResult = ResultVoUtils.getSuccessResult();
                successResult.setData(messageVo);
                result.put(messageVo.getMessageId(), successResult);
            }
        }
        return result;
    }

    @Override
    public List<SessionVo> getSessionList(Map<String, Object> data) {
        Assert.notNull(data, "请求不能为空");
        Assert.hasText((String) data.get("userId"), "userId不能为空");
        List<SessionVo> sessionVoList = new ArrayList<>();
        String userId = String.valueOf(data.get("userId"));
        long time = data.get("time") != null ? Long.valueOf(data.get("time").toString()) : System.currentTimeMillis();
        List<SessionUser> sessionUserList = sessionUserDao.findAllByUserIdAndIsDelete(userId , 0);
        if (CollectionUtils.isNotEmpty(sessionUserList)) {
            List<String> sessionIdList = sessionUserList.stream().map(SessionUser :: getSessionId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(sessionIdList)) {
                List<Session> sessionList = sessionDao.findAllBySessionIdInAndIsDeleteAndLastMessageTimeBeforeOrderByLastMessageTimeDesc(sessionIdList, 0, new Date(time));
                if (CollectionUtils.isNotEmpty(sessionList)) {
                    List<Session> sessionListTemp = Lists.partition(sessionList, 10).get(0);
                    for (Session session : sessionListTemp) {
                        SessionVo sessionVo = getSessionVo(session, userId);
                        sessionVoList.add(sessionVo);
                    }
                }
            }
        }
        return sessionVoList;
    }

    private SessionVo getSessionVo(Session session, String userId) {
        SessionVo sessionVo = SessionVo.getSessionVo();
        String sessionId = session.getSessionId();
        sessionVo.setSessionId(sessionId);
        if ("1".equals(session.getSessionType())) {
            sessionVo.setSessionType(session.getSessionType());
            UserInfoVo userInfoVo = getUserInfoBySessionId(sessionId, userId);
            if (userInfoVo != null && userInfoVo.getUserInfo() != null) {
                if (StringUtils.isNotBlank(userInfoVo.getUserInfo().getUserName())) {
                    sessionVo.setDisplayName(userInfoVo.getUserInfo().getUserName());
                }
                if (StringUtils.isNotBlank(userInfoVo.getUserInfo().getAvatarUrl())) {
                    sessionVo.setDisplayPhoto(userInfoVo.getUserInfo().getAvatarUrl());
                }
            }
        }
        List<Message> messageList = messageDao.findAllBySessionIdInAndIsDeleteOrderByCreateTimeDesc(sessionId, 0);
        if (CollectionUtils.isNotEmpty(messageList)) {
            Message message = messageList.get(0);
            sessionVo.setLastMessage(message.getContent());
            sessionVo.setLastMessageType(message.getType());
            sessionVo.setLastMessageTime(message.getCreateTime());
            String messageUserId = message.getFromUserId();
            sessionVo.setLastUserId(messageUserId);
            List<UserInfoVo> userInfoList = userService.getUserInfo(Collections.singletonList(messageUserId));
            if (CollectionUtils.isNotEmpty(userInfoList)) {
                UserInfoVo userInfoVo = userInfoList.get(0);
                if (userInfoVo.getUserInfo() != null) {
                    sessionVo.setLastUserName(userInfoVo.getUserInfo().getUserName());
                }
            }
        }
        return sessionVo;
    }

    @Override
    public Object getSessionInfo(Map<String, Object> data) {
        Assert.notNull(data, "请求不能为空");
        Assert.notNull(data.get("sessionId"), "sessionId不能为空");
        Assert.notNull(data.get("userId"), "userId不能为空");
        String sessionId = data.get("sessionId").toString();
        String userId = data.get("userId").toString();
        Map<String, Object> result = new HashMap<>();
        List<Session> sessionList = sessionDao.findAllBySessionIdAndIsDelete(sessionId, 0);
        if (CollectionUtils.isNotEmpty(sessionList)) {
            Session session = sessionList.get(0);
            if ("1".equals(session.getSessionType())) {
                UserInfoVo userInfoVo = getUserInfoBySessionId(session.getSessionId(), userId);
                if (userInfoVo != null && userInfoVo.getUserInfo() != null) {
                    if (StringUtils.isNotBlank(userInfoVo.getUserInfo().getUserName())) {
                        result.put("displayName", userInfoVo.getUserInfo().getUserName());
                    }
                }
            }
        }
        return result;
    }

    @Override
    public Object getMessage(Map<String, Object> data) {
        Assert.notNull(data, "请求不能为空");
        Assert.notNull(data.get("sessionId"), "sessionId不能为空");
        String sessionId = data.get("sessionId").toString();
        long time = data.get("time") != null ? Long.valueOf(data.get("time").toString()) : System.currentTimeMillis();
        List<MessageVo> result = new ArrayList<>();
        List<Message> messageList = messageDao.findAllBySessionIdInAndIsDeleteAndCreateTimeBeforeOrderByCreateTimeDesc(sessionId, 0, new Date(time));
        if (CollectionUtils.isNotEmpty(messageList)) {
            List<Message> messageListTemp = Lists.partition(messageList, 10).get(0);
            List<String> userIdList = messageListTemp.stream().map(Message :: getFromUserId).collect(Collectors.toList());
            Map<String, UserInfo> userInfoMap = new HashMap<>();
            List<UserInfoVo> userInfoVoList = userService.getUserInfo(userIdList);
            if (CollectionUtils.isNotEmpty(userInfoVoList)) {
                for (UserInfoVo userInfoVo : userInfoVoList) {
                    if (userInfoVo != null && userInfoVo.getUserInfo() != null) {
                        userInfoMap.put(userInfoVo.getUserInfo().getUserId(), userInfoVo.getUserInfo());
                    }
                }
            }
            for (Message message : messageListTemp) {
                MessageVo messageVo = MessageVo.changeMessageVo(message);
                String fromUserId = message.getFromUserId();
                if (userInfoMap.containsKey(fromUserId)) {
                    messageVo.setFromUserName(userInfoMap.get(fromUserId).getUserName());
                    messageVo.setFromUserAvatarUrl(userInfoMap.get(fromUserId).getAvatarUrl());
                }
                result.add(messageVo);
            }
            Collections.reverse(result);
        }
        return result;
    }

    @Override
    public List<Session> getSessionBySessionId(List<String> idList) {
        List<Session> sessionList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(idList)) {
            return sessionDao.findAllBySessionIdInAndIsDelete(idList, 0);
        }
        return sessionList;
    }

    @Override
    public List<SessionUser> getSessionUserBySessionId(List<String> idList) {
        List<SessionUser> sessionUserList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(idList)) {
            return sessionUserDao.findAllBySessionIdInAndIsDelete(idList, 0);
        }
        return sessionUserList;
    }

    @Override
    public SessionVo getSessionInfoBySessionId(Map<String, Object> data) {
        Assert.notNull(data, "请求不能为空");
        Assert.notNull(data.get("sessionId"), "sessionId不能为空");
        Assert.notNull(data.get("userId"), "userId不能为空");
        String sessionId = data.get("sessionId").toString();
        String userId = data.get("userId").toString();
        List<Session> sessionList = sessionDao.findAllBySessionIdAndIsDelete(sessionId, 0);
        if (CollectionUtils.isNotEmpty(sessionList)) {
            Session session = sessionList.get(0);
             return getSessionVo(session, userId);
        }
        return null;
    }

    private UserInfoVo getUserInfoBySessionId(String sessionId, String userId) {
        List<FriendRelation> relationList = userService.queryFriendBySessionId(Collections.singletonList(sessionId));
        if (CollectionUtils.isNotEmpty(relationList)) {
            FriendRelation relation = relationList.get(0);
            String otherId = userId.equals(relation.getMainUserId()) ? relation.getFriendUserId() : relation.getMainUserId();
            List<UserInfoVo> userInfoVoList = userService.getUserInfo(Collections.singletonList(otherId));
            if (CollectionUtils.isNotEmpty(userInfoVoList)) {
                return userInfoVoList.get(0);
            }
        }
        return null;
    }
}
